// @Author EthanScriptOn
// @Desc
package identity

import (
	"gitee.com/fatzeng/srf_switch_basic_components/tool"
	"sync/atomic"
)

// UniqueIdGenerator Unique ID generator, incremental
type UniqueIdGenerator struct {
	startingPoint  uint64
	uniqueId       uint64
	floatingFactor uint64
}

// GenerateUniqueIdGenerator Create an ID generator startingPoint-starting point floatingFactor-growth
func GenerateUniqueIdGenerator(startingPoint uint64, floatingFactor uint64) *UniqueIdGenerator {
	if floatingFactor == 0 {
		floatingFactor = 1
	}
	generator := UniqueIdGenerator{
		floatingFactor: floatingFactor,
		startingPoint:  startingPoint,
	}
	return &generator
}

// GenerateUniqueIdentifier Generate ID
func (u *UniqueIdGenerator) GenerateUniqueIdentifier() (identifier interface{}, err error) {
	defer tool.HandleErr(&err)
	for {
		currentUniqueId := atomic.LoadUint64(&u.uniqueId)
		if currentUniqueId >= u.startingPoint {
			newUniqueId := currentUniqueId + u.floatingFactor
			if atomic.CompareAndSwapUint64(&u.uniqueId, currentUniqueId, newUniqueId) {
				return newUniqueId, nil
			}
			continue
		}
		if atomic.CompareAndSwapUint64(&u.uniqueId, currentUniqueId, u.startingPoint) {
			continue
		}
	}
}
